//-------------------------------------------------------------------
//	Copyright (c) 2010-2012  Zhirnov Andrey
//	This file is part of the "UXGEN" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#ifndef _UX_SCENE_OBJECT_FACTORY_H
#define _UX_SCENE_OBJECT_FACTORY_H

#include "SceneBase.h"

namespace Engine
{
namespace Scene
{

	//
	// Scene Objects Create Params
	//

	struct TSceneObjCreateParams
	{
		struct TScene
		{
		};

		struct TSceneNode
		{
			ISceneBaseObject	*	pScene;
			ISceneBaseObject	*	pParent;
		};

		struct TSceneComponent
		{
			ISceneBaseObject	*	pScene;
			ISceneBaseObject	*	pSystem;
		};

		struct TSceneSystem
		{
			ISceneBaseObject	*	pScene;
		};
		
		union UData
		{
			TScene			sScene;
			TSceneNode		sNode;
			TSceneComponent	sComp;
			TSceneSystem	sSystem;
		};

		e_scene_object::type	eType;
		UData					sData;
		///
		TSceneObjCreateParams(): eType(e_scene_object::UNKNOWN)	{ memset( &sData, 0, sizeof(sData) ); }
	};





	//
	// Scene Object Factory
	//

	class _EXPORT_ CSceneObjectFactory : public CEngBaseObject
	{
		friend class CoreSystems::CObjectManager;
			
	public:
		typedef bool (CALLBACK *PCreateSceneObjectProc_t)(const TSceneObjCreateParams &, ISceneBaseObject *&);

	private:
		struct TSceneNodeType
		{
			PCreateSceneObjectProc_t	pProc;
			string						sTypeName;
			///
			TSceneNodeType(PCreateSceneObjectProc_t proc, const string &type): pProc(proc), sTypeName(type) {}
		};

		struct TSceneCompType
		{
			PCreateSceneObjectProc_t	pProc;
			string						sTypeName;
			///
			TSceneCompType(PCreateSceneObjectProc_t proc, const string &type): pProc(proc), sTypeName(type) {}
		};

		struct TSceneSystemType
		{
			PCreateSceneObjectProc_t	pProc;
			string						sTypeName;
			///
			TSceneSystemType(PCreateSceneObjectProc_t proc, const string &type): pProc(proc), sTypeName(type) {}
		};

		struct TSceneType
		{
			array< TSceneNodeType >		aNodeTypes;
			array< TSceneCompType >		aCompTypes;
			array< TSceneSystemType >	aSysTypes;
			PCreateSceneObjectProc_t	pCreateScene;
			string						sTypeName;
			///
			TSceneType(PCreateSceneObjectProc_t proc, const string &type): pCreateScene(proc), sTypeName(type) {}
		};

	private:
		array< TSceneType >		_aSceneTypes;

	protected:
		CSceneObjectFactory();
		~CSceneObjectFactory();

		bool  Init();
		bool _GetSceneType(const string &sTypeName, TSceneType *&pScene);

		// CEngBaseObject //
		virtual void Release();

	public:
		bool CreateScene(const string &sTypeName, ISceneBaseObject *&pScene);
		bool CreateObject(ISceneBaseObject *pScene, ISceneBaseObject *pParent, const string &sTypeName, ISceneBaseObject *&pNode);
		bool CreateComponent(ISceneBaseObject *pScene, ISceneBaseObject *pSystem, const string &sTypeName, ISceneBaseObject *&pComp);
		bool CreateSystem(ISceneBaseObject *pScene, const string &sTypeName, ISceneBaseObject *&pSystem);

		
		bool RegisterScene(const string &sTypeName, PCreateSceneObjectProc_t pProc);
		bool UnRegisterScene(const string &sTypeName);

		bool RegisterObject(const string &sSceneType, const string &sTypeName, PCreateSceneObjectProc_t pProc);
		bool UnRegisterObject(const string &sSceneType, const string &sTypeName);

		bool RegisterComponent(const string &sSceneType, const string &sTypeName, PCreateSceneObjectProc_t pProc);
		bool UnRegisterComponent(const string &sSceneType, const string &sTypeName);

		bool RegisterSystem(const string &sSceneType, const string &sTypeName, PCreateSceneObjectProc_t pProc);
		bool UnRegisterSystem(const string &sSceneType, const string &sTypeName);
		
		void Clear();
	};
	
//-------------------------------------------------------------------

}	// Scene
}	// Engine

#endif	// _UX_SCENE_OBJECT_FACTORY_H